package com.sloera.spring.aop.helloword;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Arrays;

/**
 * @author sloera
 * @create 2020/4/8
 */
public class ArithmeticCaculatoryLoggingProxy {
    //要代理的对象
    private ArithmeticCaculator target;

    public ArithmeticCaculatoryLoggingProxy(ArithmeticCaculator target) {
        this.target = target;
    }

    public ArithmeticCaculator getLoggingProxy() {
        ArithmeticCaculator proxy = null;
        //代理对象由哪一个类加载器负责加载
        ClassLoader loader = target.getClass().getClassLoader();
        //代理对象的类型，即其中有哪些方法
        Class[] interfaces = new Class[]{ArithmeticCaculator.class};
        //当调用代理对象其中的方法时， 该执行的方法
        InvocationHandler h = new InvocationHandler() {
            /*
             * @param proxy:正在返回的代理对象，一般不使用。会造成递归调用
             * @param method:正在被调用的方法
             * @param args:调用方法时传入的参数
             * @Return java.lang.Object
             * @Author SloeraN
             * @Date 2020/4/8 22:38
             */
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                String methodName = method.getName();
                //日志
                System.out.println("The method " + methodName + " begins with " + Arrays.asList(args));
                //执行方法
                Object result = null;
                try {
                    //前置通知
                    result = method.invoke(target, args);
                    //返回通知，可以访问到方法的返回值
                } catch (Exception e) {
                    //异常通知，可以访问到方法中出现的异常
                    e.printStackTrace();
                }
                //后置通知，方法可能会出现异常，访问不到方法的返回值
                //日志
                System.out.println("The method " + methodName + " ends with " + result);
                return result;
            }
        };
        proxy = (ArithmeticCaculator) Proxy.newProxyInstance(loader, target.getClass().getInterfaces(), h);
        return proxy;
    }
}
